#include "GameObjectManager.h"
#include "GameSystemManager.h"
#include "CRender.h"
#include "CLight.h"
#include "CMesh.h"
#include "CPosition.h"
#include "COrientation.h"
#include "CPhysics.h"
#include "TextOutput.h"
#include "CVelocity.h"
#include "CCamera.h"
//#include "frmObjects.h"

/*
#include "GameObject.h"
#include "GameObjTemplateMgr.h"
#include "GameCompTemplateMgr.h"
#include "GameComponent.h"
#include "GameComponentTemplate.h"
#include "GameObjectTemplate.h"
#include <string>
#include <map>
*/

GOMConfig gom_config;

GameObjectManager* GameObjectManager::mInstance = NULL;
//SceneNode* GameObjectManager::objectDecalNode = NULL;
//mCTM->registerTemplate(ctemp);
	
ObjTemplateMgr *GameObjectManager::mOTM = NULL;
CompTemplateMgr *GameObjectManager::mCTM = NULL;
//std::map<const std::string, GameObject*> GameObjectManager::getGOs() = NULL;

GameObjectManager::GameObjectManager() { 
	mOTM = new ObjTemplateMgr();
	mCTM = new CompTemplateMgr();
	numComponents = 0;
	createDecals();
	gom_config.isObjectSelected = false;
	gom_config.isHoldingItem = false;
	gom_config.objectInHand = "";
	gom_config.objectSelected = "";
	gom_config.mode = MOVE_MODE;
}

GameObjectManager::~GameObjectManager() { 

}

int GameObjectManager::getNextCompIndex() {
	return numComponents++;
}

std::map<const std::string, GameObject*> GameObjectManager::getGOs() { 
	return mGOs;
}

GameObjectManager* GameObjectManager::getSingleton() {
	if(mInstance == NULL)
		mInstance = new GameObjectManager();
	return mInstance;
}

void GameObjectManager::registerComponentTemplate(GameComponentTemplate *ctemp) {
	mCTM->registerTemplate(ctemp);
}
void GameObjectManager::registerObjectTemplate(GameObjectTemplate *otemp) {
	mOTM->registerTemplate(otemp);
	//mCTM->
}

	//void registerComponents() {
		//mCTM->registerTemplate(
	//}
	
	//GameComponent* addComponent(const comp_id_type &id) {
	//	comp_id_type family = newComp->familyID();
	//	Component *oldComp = mComponents[family];
	//	mComponents[family] = newComp;
	//	return oldComp;
	//}

//Retrieve a Game Object
GameObject* GameObjectManager::getGO(const obj_id_type &id) {
	//return mGOs[id];
	
	std::map<const comp_id_type, GameObject*>::iterator iter = mGOs.begin();
	iter = mGOs.find(id);
	if(iter != mGOs.end()) {
		return iter->second;
	}
	return NULL;
}
void GameObjectManager::deleteGO(const obj_id_type &id) {
	//mGOs[id]->clearComponents();
	//delete mGOs[id];

	std::map<const comp_id_type, GameObject*>::iterator iter = mGOs.begin();
	iter = mGOs.find(id);
	
	if(iter != mGOs.end()) {
		iter->second->clearComponents();
		mGOs.erase(iter);
		//delete iter;
	}
}

GameObject* GameObjectManager::createCustomObject(GameObject *go) {
	mGOs[go->getID()] = go;
	return mGOs[go->getID()];
}

GameObject* GameObjectManager::createObjectFromTemplate(const obj_id_type &templName,const obj_id_type &oid) { //std::string templName,
	mGOs[oid] = mOTM->createObject(templName,const_cast<obj_id_type&>(oid));
	return mGOs[oid];
}
	

void GameObjectManager::clearGameObjects() {
	std::map<const std::string, GameObject*>::iterator iter;
	for(iter = mGOs.begin(); iter != mGOs.end(); iter++) {
		//dynamic_cast<GameObject*>(iter->second)->clearComponents();
		iter->second->clearComponents();
	}
	mGOs.clear();
}

void GameObjectManager::update() { 
	std::map<const std::string, GameObject*>::iterator iter;
	for(iter = mGOs.begin(); iter != mGOs.end(); iter++) {
		//dynamic_cast<GameObject*>(iter->second)->update();
		iter->second->update();
	}
} 

void GameObjectManager::mouseMovedNotification(bool controledByGui,int x,int y) {
	if(!controledByGui) {
		if(GameSceneManager::getSingleton()->getBrush() == BRUSH_OBJECT)
		{
			if(gom_config.mode == MOVE_MODE) {
				if(gom_config.isMovingObject) {
					if(gom_config.objectSelected != "") {
						CRender *sel_obj = dynamic_cast<CRender*>(getGO(gom_config.objectSelected)->getComponent("CRender"));
						CPhysics *physics_obj = dynamic_cast<CPhysics*>(getGO(gom_config.objectSelected)->getComponent("CPhysics"));
						if(sel_obj) {
							Vector3 newPos = sel_obj->mNode->getPosition();
							if(gom_config.axisToMove == Vector3::UNIT_X)
								newPos.x -= x;
							if(gom_config.axisToMove == Vector3::UNIT_Y)
								newPos.y -= y;
							if(gom_config.axisToMove == Vector3::UNIT_Z)
								newPos.z += x;
							
							sel_obj->mNode->setPosition(newPos);
							objectDecalNode->setPosition(newPos);
							
							CPosition *obj_pos = dynamic_cast<CPosition*>(getGO(gom_config.objectSelected)->getComponent("CPosition"));
							if(obj_pos)
								obj_pos->Position = newPos; //sel_obj->mNode->getPosition();

							if(physics_obj) {
								//if(physics_obj->physicsObject) { // mActor
								//	//physics_obj->mActor->setGlobalPosition(toVec3(newPos));
								//	for(unsigned int i = 0; i < physics_obj->physicsObject->obj.size(); i++)
								//	{
								//		//NxVec3 p = physics_obj->physicsObject->obj[i]->body->getGlobalPosition();
								//		NxVec3 p = toVec3(newPos);
								//		physics_obj->physicsObject->obj[i]->body->setGlobalPosition(p);
								//	}
								//}

								//simulateOnce(0.0f);
							}
						}

						/*

						GameObject *goa = GameObjectManager::getSingleton()->getGO("piedra");
						GameObject *gob = GameObjectManager::getSingleton()->getGO("luz");

						CPosition *obja = dynamic_cast<CPosition*>(goa->getComponent("CPosition"));
						if(obja) {
							obja->Position = Vector3(1,1,1); //sel_obj->mNode->getPosition();
						}
						CPosition *cPosa = dynamic_cast<CPosition*>(goa->getComponent("CPosition"));
						CPosition *cPosb = dynamic_cast<CPosition*>(gob->getComponent("CPosition"));

						Vector3 va = cPosa->Position;
						Vector3 vb = cPosb->Position;

						static Ogre::Vector3 Position;
						CPosition *objb = dynamic_cast<CPosition*>(gob->getComponent("CPosition"));
						if(objb) {
							objb->Position = Vector3(2,2,2); //sel_obj->mNode->getPosition();
						}
						cPosa = dynamic_cast<CPosition*>(goa->getComponent("CPosition"));
						cPosb = dynamic_cast<CPosition*>(gob->getComponent("CPosition"));
						
						va = cPosa->Position;
						vb = cPosb->Position;

						va = va;

						
						CRender *cRendera = dynamic_cast<CRender*>(getGO("a")->getComponent("CRender"));
						CRender *cRenderb = dynamic_cast<CRender*>(getGO("b")->getComponent("CRender"));

						Vector3 CPosa = cPosa->Position;
						Vector3 CPosb = cPosb->Position;

						Vector3 NodePosa = cRendera->mNode->getPosition();
						Vector3 NodePosb = cRenderb->mNode->getPosition();


						CPosa = CPosb;
						*/
						//////////////////////////////////////////////////////////////////////////

					}
				}
			}
			


			if(gom_config.mode == ROTATE_MODE) {
				if(gom_config.isObjectSelected) {
					//if(gom_config.objectSelected != "") {
						if(GameSystemManager::getSingleton()->getInput()->mouseLeftButton)	{
							GameObjectManager::getSingleton()->updateObjectRotation();
						}
					//}
				}
			}
			
			if(gom_config.mode == SCALE_MODE)
				if(gom_config.isObjectSelected)
					if(gom_config.objectSelected != "")
						if(GameSystemManager::getSingleton()->getInput()->mouseLeftButton)
							GameObjectManager::getSingleton()->updateObjectScaling();
						
					
				

		}
	}
}

void GameObjectManager::mouseButtonDownNotification(bool controledByGui,unsigned int button) {
	if(button == OIS::MB_Left) {
		if(!controledByGui) {
			
			if(gom_config.isObjectSelected) {
				Ogre::RaySceneQueryResult qryResult = GameSceneManager::getSingleton()->getOgreObjectsFromMousePos();
				
				if(qryResult.empty())
					return;

				Ogre::RaySceneQueryResult::iterator i;
				for(i = qryResult.begin() ; i != qryResult.end(); i++) {
					std::string name = i->movable->getName();
						
					if(name == "move_widget_x") {
						gom_config.isMovingObject = true;
						gom_config.axisToMove = Vector3::UNIT_X;
					}
					if(name == "move_widget_y") {
						gom_config.isMovingObject = true;
						gom_config.axisToMove = Vector3::UNIT_Y;
					}
					if(name == "move_widget_z") {
						gom_config.isMovingObject = true;
						gom_config.axisToMove = Vector3::UNIT_Z;
					}
					
					if(name == "sphere") { //
						if(gom_config.mode == MOVE_MODE) {
							if(gom_config.objectSelected != "") {
								gom_config.objectInHand = gom_config.objectSelected;
								gom_config.isHoldingItem = true;
							}
						} else {
							gom_config.isMovingObject = true;
						}
					}
				}
					//std::string objectOwner = Ogre::any_cast<std::string> (i->movable->getUserAny()) ;
					//return objectOwner;

			}
		}
			
	}
}
void GameObjectManager::reloadGO(std::string goName) {
	
	if(gom_config.objectSelected != "") {
		CPhysics *physics = dynamic_cast<CPhysics*>(GameObjectManager::getSingleton()->getGO(goName)->getComponent("CPhysics"));
		CMesh *mesh = dynamic_cast<CMesh*>(GameObjectManager::getSingleton()->getGO(goName)->getComponent("CMesh"));
		CRender *mov = dynamic_cast<CRender*>(GameObjectManager::getSingleton()->getGO(goName)->getComponent("CRender"));
		if(physics) {
			Vector3 scale = mov->mNode->getScale();
			Vector3 position = mov->mNode->getPosition();
			Quaternion orientation = mov->mNode->getOrientation();
			std::string meshName = mesh->meshFileName;
			bool isRagdoll = false;
			//int id = physics->id;
			
			//deleteActor(goName);

			GameObjectManager::getSingleton()->deleteGO(goName);
						

			GameObject *GO = new GameObject(goName);
			
			CPosition *mPos = new CPosition();
			COrientation *mOr = new COrientation();
			CPhysics *mCPhysics = new CPhysics();
			CMesh *mMesh = new CMesh(meshName);
			std::string physics_file = meshName.substr(0,meshName.length() - 4) + "phs";
			CRender *mMov = new CRender();
			GO->setComponent(mPos);
			GO->setComponent(mOr);
			GO->setComponent(mMesh);
			GO->setComponent(mMov);
			GO->setComponent(mCPhysics);
			
			GO->setup();
			
			GameObjectManager::getSingleton()->createCustomObject(GO);

			//GameSystemManager::getSingleton()->getPhysics()->shutdown();
			//GameSystemManager::getSingleton()->createPhysics();
			
			//createBody(isRagdoll,physics_file,goName.c_str(),scale.x,scale.y,scale.z,position.x,position.y,position.z);
			
			mMov->mNode->setScale(scale);
			mMov->mNode->setPosition(position);
			mMov->mNode->setOrientation(orientation);

		}
		
	}

}
void GameObjectManager::mouseButtonUpNotification(bool controledByGui,unsigned int button) {
	if(button == OIS::MB_Left) {
		if(!controledByGui) {
			if(GameSceneManager::getSingleton()->getBrush() == BRUSH_OBJECT)
			{
				if(gom_config.isMovingObject) {
					if(gom_config.mode == SCALE_MODE) {
						if(gom_config.objectSelected != "") {
							CPhysics *physics = dynamic_cast<CPhysics*>(GameObjectManager::getSingleton()->getGO(gom_config.objectSelected)->getComponent("CPhysics"));
							CMesh *render = dynamic_cast<CMesh*>(GameObjectManager::getSingleton()->getGO(gom_config.objectSelected)->getComponent("CMesh"));
							if(physics) {
						//		Vector3 scale = mov->mNode->getScale();
						//		std::string objName = gom_config.objectSelected;
						//		std::string meshName = render->meshFileName;
						//		GameObjectManager::getSingleton()->deleteGO(objName);
								
								reloadGO(gom_config.objectSelected);
								//simulateOnce(0.0f);
								//nWorld->simulate((NxReal)0.0f); //1.0f/40.0f //(NxReal) time
								//nWorld->flushStream();
								//nWorld->fetchResults(NX_RIGID_BODY_FINISHED, true);
								
							}
							
						}

					}
					gom_config.objectInHand = "";
					gom_config.isMovingObject = false;
				} else {
					
					if(gom_config.objectSelected != "") {
						CRender *prev_mov = dynamic_cast<CRender*>(getGO(gom_config.objectSelected)->getComponent("CRender"));
						if(prev_mov) {
							objectDecalNode->setVisible(false);
							prev_mov->mNode->showBoundingBox(false);
						}
					}
					
					gom_config.objectSelected = GameSceneManager::getSingleton()->getObjectNameFromMousePos();
					if(gom_config.objectSelected != "") {
						CRender *mov = dynamic_cast<CRender*>(getGO(gom_config.objectSelected)->getComponent("CRender"));
						if(mov) {
							mov->mNode->showBoundingBox(true);
							objectDecalNode->setVisible(true);
							objectDecalNode->setPosition(mov->mNode->getPosition());
							gom_config.isObjectSelected = true;
							gom_config.isMovingObject = false;
							gom_config.objectInHand = "";

							GameSystemManager::getSingleton()->getGUI()->updateObjectsWindow();
						}
					}
				}
			}
		}
	}
}
void GameObjectManager::setVisibleObjectDecal(bool visible) {
	objectDecalNode->setVisible(visible);	
}

void GameObjectManager::updateObjectDecalPosition(Vector3 pos) {
	if(GameSceneManager::getSingleton()->getBrush() == BRUSH_OBJECT)
	{
		objectDecalNode->setPosition(pos);
	}
}

void GameObjectManager::updateObjectRotation() {
	if(GameSceneManager::getSingleton()->getBrush() == BRUSH_OBJECT)	{
		if(gom_config.mode == ROTATE_MODE) {
			if(gom_config.isObjectSelected) {
				if(GameSystemManager::getSingleton()->getInput()->mouseLeftButton)	{
					if(gom_config.objectSelected != "") {
						Ogre::Quaternion rot;
						if(gom_config.axisToMove == Vector3::UNIT_X)
							rot = updateObjectYawMove();
						if(gom_config.axisToMove == Vector3::UNIT_Y) 
							rot = updateObjectPitchMove();
						if(gom_config.axisToMove == Vector3::UNIT_Z)
							rot = updateObjectRollMove();
						
						CRender *cm = dynamic_cast<CRender*>((GameObjectManager::getSingleton()->getGO(gom_config.objectSelected))->getComponent("CRender"));
						if(cm) {
							COrientation *obj_orient = dynamic_cast<COrientation*>(getGO(gom_config.objectSelected)->getComponent("COrientation"));
							if(obj_orient)
								obj_orient->Orientation = rot;
							
							CPhysics *po = dynamic_cast<CPhysics*>(getGO(gom_config.objectSelected)->getComponent("CPhysics"));
							if(po) {
								//NxMat33 mat = toNxMat33(cm->mNode->getOrientation());
								//po->mActor->setGlobalOrientation(mat);
								//simulateOnce(0.0f);
							}
						}

					}
				}
			}
		}
	}
}

void GameObjectManager::updateObjectScaling() {
	

	CRender *cm = dynamic_cast<CRender*>((GameObjectManager::getSingleton()->getGO(gom_config.objectSelected))->getComponent("CRender"));
	if(cm) {
		OIS::MouseState ms = GameSystemManager::getSingleton()->getInput()->getMouseStat();
		
		float xrel = (ms.X.rel * 0.03);
		
		Vector3 obj_scale = cm->mNode->getScale();
		obj_scale.x += xrel;
		obj_scale.y += xrel;
		obj_scale.z += xrel; 
		
		//OgreQueueText::instance()->Addf("obj_scale %f",obj_scale.x);

		cm->mNode->setScale(obj_scale);
		

		/*
		CPhysics *po = dynamic_cast<CPhysics*>(getGO(gom_config.objectSelected)->getComponent("CPhysics"));
		if(po) {
			NxMat33 mat = toNxMat33(cm->mNode->getScale());
			// ->setGlobalOrientation(mat);
			//po->mActor->getShapes
			
			NxU32 nbShapes = po->mActor->getNbShapes();
			NxShape *const*shapes = po->mActor->getShapes();

			while (nbShapes--)
			{
			   shapes[nbShapes]->setGroup(group);
				shapes[nbShapes]->
			}

			simulateOnce(0.0f);
		}
		*/

	}
}

Ogre::Quaternion GameObjectManager::updateObjectYawMove() {
	CRender *cm = dynamic_cast<CRender*>((GameObjectManager::getSingleton()->getGO(gom_config.objectSelected))->getComponent("CRender"));
	if(cm) {
		//CEGUI::Slider* sld = (CEGUI::Slider*) CEGUI::WindowManager::getSingleton().getWindow("Objects/sldYaw");
		OIS::MouseState ms = GameSystemManager::getSingleton()->getInput()->getMouseStat();
		cm->mNode->yaw( Degree(-(ms.X.rel) * 0.3) );
		return cm->mNode->getOrientation();
	}
	return Ogre::Quaternion::IDENTITY;
}
Ogre::Quaternion GameObjectManager::updateObjectPitchMove() {
	CRender *cm = dynamic_cast<CRender*>((GameObjectManager::getSingleton()->getGO(gom_config.objectSelected))->getComponent("CRender"));
	if(cm) {
		//CEGUI::Slider* sld = (CEGUI::Slider*) CEGUI::WindowManager::getSingleton().getWindow("Objects/sldYaw");
		OIS::MouseState ms = GameSystemManager::getSingleton()->getInput()->getMouseStat();
		cm->mNode->pitch( Degree(-(ms.Y.rel) * 0.3) );

		return cm->mNode->getOrientation();
	}
	return Ogre::Quaternion::IDENTITY;
}
Ogre::Quaternion GameObjectManager::updateObjectRollMove() {
	CRender *cm = dynamic_cast<CRender*>((GameObjectManager::getSingleton()->getGO(gom_config.objectSelected))->getComponent("CRender"));
	if(cm) {
		//CEGUI::Slider* sld = (CEGUI::Slider*) CEGUI::WindowManager::getSingleton().getWindow("Objects/sldYaw");
		OIS::MouseState ms = GameSystemManager::getSingleton()->getInput()->getMouseStat();
		cm->mNode->roll( Degree(-(ms.X.rel) * 0.3) );
		return cm->mNode->getOrientation();
	}
	return Ogre::Quaternion::IDENTITY;
}

//void GameObjectManager::addCustomGO(std::string objName, bool isMesh,bool isLight,bool isRagdoll, std::string meshFileName, float xScale = 1.0f, float yScale = 1.0f, float zScale = 1.0f, float xPosition = 0.0f, float yPosition = 0.0f, float zPosition  = 0.0f) {
void GameObjectManager::addCustomGO(std::string objName, bool isMesh,bool isLight,bool isRagdoll, std::string meshFileName, float xScale, float yScale, float zScale, float xPosition, float yPosition, float zPosition) {

	GameSceneManager::getSingleton()->setBrush(BRUSH_OBJECT);

	if(objName != "")
	{
		if(isMesh && meshFileName.c_str() == "") {
			OgreQueueText::instance()->Add("Select a mesh to create first!");
			return;
		}

		GameObject *GO = new GameObject(objName.c_str());
		
		CPosition *mPos = new CPosition();
		COrientation *mOr = new COrientation();
		CPhysics *mCPhysics = new CPhysics();
		CMesh *mMesh;
		std::string phsf;

		if(isMesh) {
			mMesh = new CMesh(meshFileName);
			phsf = meshFileName.substr(0,meshFileName.length() - 4) + "phs";
			//if(ResourceGroupManager::getSingleton().resourceExists("General",phsf))
				//mCPhysics = new CPhysics(phsf,false);
		} else {
			mMesh = new CMesh("arrow.mesh");
		}

		CRender *mMov = new CRender();
		
		if(isLight) {
			CLight *mLight = new CLight();
			GO->setComponent(mLight);
		}

		GO->setComponent(mPos);
		GO->setComponent(mOr);
		GO->setComponent(mMesh);
		GO->setComponent(mMov);
		
		//Only create the Physics component where a .phs file is found, wich contains all physics data
		if(ResourceGroupManager::getSingleton().resourceExists("General",phsf))
			GO->setComponent(mCPhysics);
		
		GO->setup();
		
		createCustomObject(GO);
	
		if(ResourceGroupManager::getSingleton().resourceExists("General",phsf)) {
			//createBody(isRagdoll,phsf,objName.c_str(),xScale,yScale,zScale,xPosition,yPosition,zPosition);

			//nWorld->simulate((NxReal)0.0f); //1.0f/40.0f //(NxReal) time
			//nWorld->flushStream();
			//nWorld->fetchResults(NX_RIGID_BODY_FINISHED, true);
		
			//simulateOnce(0.0f);
		} else {
			gom_config.objectInHand = objName;
			gom_config.isHoldingItem = true;
		}
		

	}

}

//Movable node controllers
void GameObjectManager::createDecals() {

	SceneManager* mSceneMgr = GameSceneManager::getSingleton()->getSceneManager();

	objectDecalNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("move_widget");
	SceneNode* node_x = objectDecalNode->createChildSceneNode("move_widget_x");
	SceneNode* node_y = objectDecalNode->createChildSceneNode("move_widget_y");
	SceneNode* node_z = objectDecalNode->createChildSceneNode("move_widget_z");
	SceneNode* sphereNode = objectDecalNode->createChildSceneNode("sphereNode");

	node_x->showBoundingBox(false);
	node_y->showBoundingBox(false);
	node_z->showBoundingBox(false);
	sphereNode->showBoundingBox(false);

	node_x->yaw(-Degree(90));
	node_y->pitch(Degree(90));
	node_z->yaw(Degree(180));

	//Entities
	Entity* entityZ = mSceneMgr->createEntity("move_widget_z", "arrow.mesh");
	Entity* entityX = mSceneMgr->createEntity("move_widget_x", "arrow.mesh");
	Entity* entityY = mSceneMgr->createEntity("move_widget_y", "arrow.mesh");
	Entity* entitySphere = mSceneMgr->createEntity("sphere", "sphere.mesh");

	//Sphere material properties
	entitySphere->setCastShadows(false);
	entitySphere->setMaterialName("SelectionIndicatorSphere");
	sphereNode->attachObject(entitySphere);
	sphereNode->setScale(0.03,0.03,0.03);

	MaterialPtr matptr = entitySphere->getSubEntity(0)->getMaterial();
	Ogre::Pass *pass = matptr->getTechnique(0)->getPass(0);
	pass->setSelfIllumination(1,1,0);

	//ZZ arrows
	//entityZ->setNormaliseNormals(true);	
	entityZ->setCastShadows(false);
	entityZ->setMaterialName("SelectionIndicatorBlue");
	node_z->attachObject(entityZ);
	
	matptr = entityZ->getSubEntity(0)->getMaterial();
	pass = matptr->getTechnique(0)->getPass(0);
	pass->setSelfIllumination(0,0,1);

	//XX arrows
	entityX->setCastShadows(false);
	entityX->setMaterialName("SelectionIndicatorRed");
	node_x->attachObject(entityX);
	
	matptr = entityX->getSubEntity(0)->getMaterial();
	pass = matptr->getTechnique(0)->getPass(0);
	pass->setSelfIllumination(1,0,0);

	//YY arrows
	entityY->setCastShadows(false);
	entityY->setMaterialName("SelectionIndicatorGreen");
	node_y->attachObject(entityY);

	matptr = entityY->getSubEntity(0)->getMaterial();
	pass = matptr->getTechnique(0)->getPass(0);
	pass->setSelfIllumination(0,1,0);

	Vector3 nodeXPos = objectDecalNode->getPosition();
	nodeXPos.x += 20;
	node_x->setPosition(nodeXPos);

	Vector3 nodeYPos = objectDecalNode->getPosition();
	nodeYPos.y += 20;
	node_y->setPosition(nodeYPos);

	Vector3 nodeZPos = objectDecalNode->getPosition();
	nodeZPos.z += 20;
	node_z->setPosition(nodeZPos);

	node_x->scale(1,1,2);
	node_y->scale(1,1,2);
	node_z->scale(1,1,2);
	objectDecalNode->scale(1.2,1.2,1.2);
}

void GameObjectManager::loadGameObjectsFromXML(TiXmlElement* mElem) {
	
	std::string mObjectName;
	bool mIsMesh;
	bool mIsLight;
	bool mIsRagdoll;
	string mMeshFileName;
	
	TiXmlHandle hRoot(0);
	hRoot = TiXmlHandle(mElem);

	int i;
	i = 0;
	
	TiXmlElement* mObjElem = hRoot.Child("Object",0).Element();

	while (mObjElem) {
			
		if(mObjElem) {
			//Get object name and store it
			TiXmlAttribute* mObjAttrib; 
			mObjAttrib = mObjElem->FirstAttribute();
			if(mObjAttrib)
				mObjectName = mObjAttrib->Value();
		}
			
		mIsMesh = false;
		mIsLight = false;
		mIsRagdoll = false;
		mMeshFileName = "";

		TiXmlElement* mCMeshElem;
		TiXmlElement* mCRenderElem;
		TiXmlElement* mCLightElem;
		TiXmlElement* mCPhysicsElem;
		TiXmlElement* mCPositionElem;
		TiXmlElement* mCOrientationElem;

		mCMeshElem = mObjElem->FirstChildElement("CMesh");
		if(mCMeshElem)
			mMeshFileName = mCMeshElem->Attribute("meshFileName");
		
		mCRenderElem = mObjElem->FirstChildElement("CRender");
		if(mCRenderElem)
			mIsMesh = Ogre::StringConverter::parseBool(mCRenderElem->Attribute("Value"));
		
		mCLightElem = mObjElem->FirstChildElement("CLight");
		if(mCLightElem)
			mIsLight = true;

		mCPhysicsElem = mObjElem->FirstChildElement("CPhysics");
		if(mCPhysicsElem)
			mIsRagdoll = true;

		mCPositionElem = mObjElem->FirstChildElement("CPosition");
		mCOrientationElem = mObjElem->FirstChildElement("COrientation");

		GameObject *mGO;

		mGO = GameObjectManager::getSingleton()->getGO(mObjectName);

		if(!mGO) {
			GameObjectManager::getSingleton()->addCustomGO(mObjectName,mIsMesh,mIsLight,mIsRagdoll,mMeshFileName);
			mGO = GameObjectManager::getSingleton()->getGO(mObjectName);
		}

		gom_config.objectInHand = "";
		gom_config.isHoldingItem = false;

		CRender *mCRender = dynamic_cast<CRender*>(mGO->getComponent("CRender"));
		CPhysics *mCPhysics = dynamic_cast<CPhysics*>(mGO->getComponent("CPhysics"));
		CPosition *mCPosition = dynamic_cast<CPosition*>(mGO->getComponent("CPosition"));
		COrientation *mCOrientation = dynamic_cast<COrientation*>(mGO->getComponent("COrientation"));
		CLight *mCLight = dynamic_cast<CLight*>(mGO->getComponent("CLight"));
		
		if(mCPositionElem && mCPosition) {
			mCPosition->Position.x = Ogre::StringConverter::parseReal(mCPositionElem->Attribute("x"));
			mCPosition->Position.y = Ogre::StringConverter::parseReal(mCPositionElem->Attribute("y"));
			mCPosition->Position.z = Ogre::StringConverter::parseReal(mCPositionElem->Attribute("z"));
		}
		if(mCOrientationElem && mCOrientation) {
			mCOrientation->Orientation.w = Ogre::StringConverter::parseReal(mCOrientationElem->Attribute("w"));
			mCOrientation->Orientation.x = Ogre::StringConverter::parseReal(mCOrientationElem->Attribute("x"));
			mCOrientation->Orientation.y = Ogre::StringConverter::parseReal(mCOrientationElem->Attribute("y"));
			mCOrientation->Orientation.z = Ogre::StringConverter::parseReal(mCOrientationElem->Attribute("z"));
		}

		if(mCRender) {
			Vector3 newPos; // = mCRender->mNode->getPosition();
			if(mCPosition)
				newPos = mCPosition->Position;

			mCRender->mNode->setPosition(newPos);
			mCRender->mNode->setScale(Ogre::StringConverter::parseVector3(mCRenderElem->Attribute("Scale")));

			if(mCOrientation)
				mCRender->mNode->setOrientation(mCOrientation->Orientation);

			if(mCLight) {
				unsigned int lt = Ogre::StringConverter::parseUnsignedInt(mCLightElem->Attribute("Light_Type"));
				if(lt == Ogre::Light::LT_DIRECTIONAL) {
					mCLight->mLight->setType(Ogre::Light::LT_DIRECTIONAL);
				} else if (lt == Ogre::Light::LT_POINT) {
					mCLight->mLight->setType(Ogre::Light::LT_POINT);
				} else if(lt == Ogre::Light::LT_SPOTLIGHT) {
					mCLight->mLight->setType(Ogre::Light::LT_SPOTLIGHT);
					
					Real SpotInner = Ogre::StringConverter::parseReal(mCLightElem->Attribute("SpotLightRangeInner"));
					Real SpotOuter = Ogre::StringConverter::parseReal(mCLightElem->Attribute("SpotLightRangeOuter"));

					Ogre::Radian SpotInnerRad = (Ogre::Radian)Ogre::Math::AngleUnitsToRadians(SpotInner);
					Ogre::Radian SpotOuterRad = (Ogre::Radian)Ogre::Math::AngleUnitsToRadians(SpotOuter);

					mCLight->mLight->setSpotlightRange(SpotInnerRad,SpotOuterRad);


				} else {
					mCLight->mLight->setType(Ogre::Light::LT_POINT);
				}
				
				Real AttenuationRange = Ogre::StringConverter::parseReal(mCLightElem->Attribute("AttenuationRange"));
				Real AttenuationConstant = Ogre::StringConverter::parseReal(mCLightElem->Attribute("AttenuationConstant"));
				Real AttenuationLinear = Ogre::StringConverter::parseReal(mCLightElem->Attribute("AttenuationLinear"));
				Real AttenuationQuadratic = Ogre::StringConverter::parseReal(mCLightElem->Attribute("AttenuationQuadratic"));
				
				mCLight->mLight->setAttenuation(AttenuationRange,AttenuationConstant,AttenuationLinear,AttenuationQuadratic);
				
				ColourValue DiffColour = Ogre::StringConverter::parseColourValue(mCLightElem->Attribute("DiffuseColour"));
				ColourValue SpecColour = Ogre::StringConverter::parseColourValue(mCLightElem->Attribute("SpecularColour"));

				mCLight->mLight->setDiffuseColour(DiffColour);
				mCLight->mLight->setSpecularColour(SpecColour);
				
			}

			if(mCPhysics) {
				//if(mCPhysics->physicsObject) { // mActor
				//	for(unsigned int i = 0; i < mCPhysics->physicsObject->obj.size(); i++) {
				//		NxVec3 p = toVec3(newPos);
				//		mCPhysics->physicsObject->obj[i]->body->setGlobalPosition(p);
				//	}
				//}

				//simulateOnce(0.0f);
			}
		}

		//////////////////////////////////////////////////////////////////////////
		//mObjElem = mElem->NextSiblingElement();
		i++;
		mObjElem = hRoot.Child("Object",i).Element();

	}
	
	GameSystemManager::getSingleton()->getGUI()->updateGameObjects();

	//fillObjectsList();
	//GameSystemManager::getSingleton()->getGUI()->addImageToControl
}



void GameObjectManager::saveGameObjectsToXML(TiXmlElement* mElem)
{

/*
gom_config.isObjectSelected = false;
gom_config.isHoldingItem = false;
gom_config.objectInHand = "";
gom_config.objectSelected = "";
gom_config.mode = MOVE_MODE;
*/
	
	std::map<const std::string, GameObject*>::iterator iter;
	for(iter = mGOs.begin(); iter != mGOs.end(); iter++) {
		CCamera *cCam = dynamic_cast<CCamera*>(iter->second->getComponent("CCamera"));
		if(!cCam) {
			
			TiXmlElement* mObject;
			mObject = new TiXmlElement("Object");  
			mElem->LinkEndChild(mObject);
			
			mObject->SetAttribute("objName",iter->second->getID().c_str());
			
			CRender *cRender = dynamic_cast<CRender*>(iter->second->getComponent("CRender"));
			if(cRender) {
				TiXmlElement* mRenderElem;
				mRenderElem = new TiXmlElement("CRender");
				mObject->LinkEndChild(mRenderElem);
				mRenderElem->SetAttribute("Value","true");
				mRenderElem->SetAttribute("Scale",Ogre::StringConverter::toString(cRender->mNode->getScale()).c_str());
			}
			
			CLight *cLight = dynamic_cast<CLight*>(iter->second->getComponent("CLight"));
			if(cLight) {
				TiXmlElement* mLightElem;
				mLightElem = new TiXmlElement("CLight");
				mObject->LinkEndChild(mLightElem);
				mLightElem->SetAttribute("Light_Type",Ogre::StringConverter::toString(cLight->mLight->getType()).c_str());
				
				if(cLight->mLight->getType() == Ogre::Light::LightTypes::LT_SPOTLIGHT) {
					mLightElem->SetAttribute("SpotLightRangeInner",Ogre::StringConverter::toString(cLight->mLight->getSpotlightInnerAngle()).c_str());
					mLightElem->SetAttribute("SpotLightRangeOuter",Ogre::StringConverter::toString(cLight->mLight->getSpotlightOuterAngle()).c_str());
				}

				mLightElem->SetAttribute("AttenuationRange",Ogre::StringConverter::toString(cLight->mLight->getAttenuationRange()).c_str());
				mLightElem->SetAttribute("AttenuationConstant",Ogre::StringConverter::toString(cLight->mLight->getAttenuationConstant()).c_str());
				mLightElem->SetAttribute("AttenuationLinear",Ogre::StringConverter::toString(cLight->mLight->getAttenuationLinear()).c_str());
				mLightElem->SetAttribute("AttenuationQuadratic",Ogre::StringConverter::toString(cLight->mLight->getAttenuationQuadric()).c_str());
				mLightElem->SetAttribute("DiffuseColour",Ogre::StringConverter::toString(cLight->mLight->getDiffuseColour()).c_str());
				mLightElem->SetAttribute("SpecularColour",Ogre::StringConverter::toString(cLight->mLight->getSpecularColour()).c_str());
				
				/*
				cLight->mLight->setAttenuation(range,constant,linear,quadratic);
				if(light_type == Ogre::Light::LT_SPOTLIGHT)
				cLight->mLight->setSpotlightRange(inner,outer);

				cLight->mLight->setDiffuseColour(difColour);
				cLight->mLight->setSpecularColour(specColour);
				*/

			}
			
			//cPos = NULL;
			CPosition *cPos = dynamic_cast<CPosition*>(iter->second->getComponent("CPosition"));
			//CPosition *cPos = dynamic_cast<CPosition*>(GameObjectManager::getSingleton()->getGO(iter->second->getID())->getComponent("CPosition"));
			
			if(cPos) {
				TiXmlElement* mPositiontElem;
				mPositiontElem = new TiXmlElement("CPosition");
				mObject->LinkEndChild(mPositiontElem);
				mPositiontElem->SetAttribute("x",Ogre::StringConverter::toString(cPos->Position.x).c_str());
				mPositiontElem->SetAttribute("y",Ogre::StringConverter::toString(cPos->Position.y).c_str());
				mPositiontElem->SetAttribute("z",Ogre::StringConverter::toString(cPos->Position.z).c_str());
			}		
			COrientation *cOrient = dynamic_cast<COrientation*>(iter->second->getComponent("COrientation"));
			if(cOrient) {
				TiXmlElement* mOrientElem;
				mOrientElem = new TiXmlElement("COrientation");
				mObject->LinkEndChild(mOrientElem);
				mOrientElem->SetAttribute("w",Ogre::StringConverter::toString(cOrient->Orientation.w).c_str());
				mOrientElem->SetAttribute("x",Ogre::StringConverter::toString(cOrient->Orientation.x).c_str());
				mOrientElem->SetAttribute("y",Ogre::StringConverter::toString(cOrient->Orientation.y).c_str());
				mOrientElem->SetAttribute("z",Ogre::StringConverter::toString(cOrient->Orientation.z).c_str());
			}	

			CVelocity *cVel = dynamic_cast<CVelocity*>(iter->second->getComponent("CVelocity"));
			if(cVel) {
				TiXmlElement* mVelElem;
				mVelElem = new TiXmlElement("CVelocity");
				mObject->LinkEndChild(mVelElem);
				mVelElem->SetAttribute("Velocity",Ogre::StringConverter::toString(cVel->Velocity).c_str());
			}	

			CMesh *cMesh = dynamic_cast<CMesh*>(iter->second->getComponent("CMesh"));
			if(cMesh) {
				TiXmlElement* mMeshElem;
				mMeshElem = new TiXmlElement("CMesh");
				mObject->LinkEndChild(mMeshElem);
				mMeshElem->SetAttribute("meshFileName",cMesh->meshFileName.c_str());
			}
		}			

	}
	
	/*
	GameObject *GO = new GameObject(objName.c_str());

	CPosition *mPos = new CPosition();
	COrientation *mOr = new COrientation();
	CPhysics *mCPhysics = new CPhysics();
	CMesh *mMesh;
	std::string phsf;

	if(isMesh) {
		mMesh = new CMesh(gom_config.selectedMesh);
		phsf = gom_config.selectedMesh.substr(0,gom_config.selectedMesh.length() - 4) + "phs";
		if(ResourceGroupManager::getSingleton().resourceExists("General",phsf))
			mCPhysics = new CPhysics(phsf,false);
	} else {
		mMesh = new CMesh("arrow.mesh");
	}

	CRender *mMov = new CRender();

	if(isLight) {
		CLight *mLight = new CLight();
		GO->setComponent(mLight);
	}

	GO->setComponent(mPos);
	GO->setComponent(mOr);
	GO->setComponent(mMesh);
	GO->setComponent(mMov);

	//Only create the Physics component where a .phs file is found, wich contains all physics data
	if(ResourceGroupManager::getSingleton().resourceExists("General",phsf))
		GO->setComponent(mCPhysics);

*/

/*
	mElem->SetAttribute("numObjects",Ogre::StringConverter::toString(sky_config.isLoaded).c_str());
	mElem->SetAttribute("ambientLightRed",Ogre::StringConverter::toString(sky_config.ambientLight.r).c_str());
	mElem->SetAttribute("ambientLightGreen",Ogre::StringConverter::toString(sky_config.ambientLight.g).c_str());
	mElem->SetAttribute("ambientLightBlue",Ogre::StringConverter::toString(sky_config.ambientLight.b).c_str());

	mElem->SetAttribute("diffuseLightRed",Ogre::StringConverter::toString(sky_config.diffuseLight.r).c_str());
	mElem->SetAttribute("diffuseLightGreen",Ogre::StringConverter::toString(sky_config.diffuseLight.g).c_str());
	mElem->SetAttribute("diffuseLightBlue",Ogre::StringConverter::toString(sky_config.diffuseLight.b).c_str());

	mElem->SetAttribute("specularLightRed",Ogre::StringConverter::toString(sky_config.specularLight.r).c_str());
	mElem->SetAttribute("specularLightGreen",Ogre::StringConverter::toString(sky_config.specularLight.g).c_str());
	mElem->SetAttribute("specularLightBlue",Ogre::StringConverter::toString(sky_config.specularLight.b).c_str());

	mElem->SetAttribute("manageLights",Ogre::StringConverter::toString(sky_config.manageLights).c_str());
	mElem->SetAttribute("cloudsSpeed",Ogre::StringConverter::toString(sky_config.cloudsSpeed).c_str());
	mElem->SetAttribute("cloudsCover",Ogre::StringConverter::toString(sky_config.cloudsCover).c_str());
	mElem->SetAttribute("cloudsBendTime",Ogre::StringConverter::toString(sky_config.cloudsBendTime).c_str());
	mElem->SetAttribute("timeScale",Ogre::StringConverter::toString(sky_config.timeScale).c_str());
*/
}

void GameObjectManager::setAttribute(std::string name,std::string  value)
{

	if(name == "isLoaded")
		sky_config.isLoaded = Ogre::StringConverter::parseBool(value);
	if(name == "ambientLightRed")
		sky_config.ambientLight.r = Ogre::StringConverter::parseReal(value);
	if(name == "ambientLightGreen")
		sky_config.ambientLight.g = Ogre::StringConverter::parseReal(value);
	if(name == "ambientLightBlue")
		sky_config.ambientLight.b = Ogre::StringConverter::parseReal(value);
	if(name == "diffuseLightRed")
		sky_config.diffuseLight.r = Ogre::StringConverter::parseReal(value);;
	if(name == "diffuseLightGreen")
		sky_config.diffuseLight.g = Ogre::StringConverter::parseReal(value);
	if(name == "diffuseLightBlue")
		sky_config.diffuseLight.b = Ogre::StringConverter::parseReal(value);
	if(name == "specularLightRed")
		sky_config.specularLight.r = Ogre::StringConverter::parseReal(value);
	if(name == "specularLightGreen")
		sky_config.specularLight.g = Ogre::StringConverter::parseReal(value);
	if(name == "specularLightBlue")
		sky_config.specularLight.b = Ogre::StringConverter::parseReal(value);
	if(name == "manageLights")
		sky_config.manageLights = Ogre::StringConverter::parseBool(value);
	if(name == "cloudsSpeed")
		sky_config.cloudsSpeed = Ogre::StringConverter::parseReal(value);
	if(name == "cloudsCover")
		sky_config.cloudsCover = Ogre::StringConverter::parseReal(value);
	if(name == "cloudsBendTime")
		sky_config.cloudsBendTime = Ogre::StringConverter::parseReal(value);
	if(name == "timeScale")
		sky_config.timeScale = Ogre::StringConverter::parseReal(value);
}
